package com.sojoys.artifact.plugin.disruptor;

import java.util.List;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.jfinal.plugin.IPlugin;
import com.lmax.disruptor.EventHandler;
import com.lmax.disruptor.LiteBlockingWaitStrategy;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import com.lmax.disruptor.dsl.ProducerType;
import com.sojoys.artifact.constant.ConfigConstant;
import com.sojoys.artifact.manager.PropManager;
import com.xiaoleilu.hutool.util.ClassUtil;

@SuppressWarnings({ "rawtypes", "unchecked" })
public class DisruptorPlugin implements IPlugin {

	static final Logger log = LoggerFactory.getLogger(DisruptorPlugin.class);
	private static Disruptor<ArtifactEvent> disruptor;
	
	@Override
	public boolean start() {
		if (disruptor==null) {
			int bufferSize = 1024;
			ThreadFactory threadFactory = Executors.defaultThreadFactory();
			disruptor = new Disruptor<>(new ArtifactEventFactory(), bufferSize, threadFactory, ProducerType.SINGLE,
					new LiteBlockingWaitStrategy());

			ArtifactEventHandler[] consumers = new ArtifactEventHandler[2];
			for (int i = 0; i < consumers.length; i++) {
				consumers[i] = new ArtifactEventHandler();
			}
			scanListeners();
			
			disruptor.start();
		}
		return true;
	}

	@Override
	public boolean stop() {
		if (disruptor!=null) {
			disruptor.shutdown();			
		}
		return true;
	}

	
	private void scanListeners() {
		Set<Class<?>> scanClasses = ClassUtil.scanPackageBySuper(PropManager.get(ConfigConstant.CONFIG_SCAN_DISRUPTOR),EventHandler.class);
//		Set<Class<?>> scanClasses = ClassUtil.scanPackageBySuper("com.sojoys.artifact.plugin.disruptor",EventHandler.class);
		List<EventHandler> eventHandlers = Lists.newArrayList();
		for (Class<?> scanClass : scanClasses) {
			Object handler = ClassUtil.newInstance(scanClass);
			eventHandlers.add((EventHandler) handler);
		}
		disruptor.handleEventsWith(eventHandlers.toArray(new EventHandler[0]));
	}

	public static void createEvent(int eventType, Object param) {
		if (disruptor==null) {
			log.error("DisruptorPlugin Not Start");
		}
		// 发布事件
		RingBuffer<ArtifactEvent> ringBuffer = disruptor.getRingBuffer();
		long sequence = ringBuffer.next();// 请求下一个事件序号；

		try {
			ArtifactEvent event = ringBuffer.get(sequence);// 获取该序号对应的事件对象；
			event.setEventType(eventType);
			event.setParam(param);
		} finally {
			ringBuffer.publish(sequence);// 发布事件；
		}
	}
}
